/**
 * Test Spec (using Jasmine Java Script Unit Test Framework)
 * http://pivotal.github.com/jasmine/
 * 
 * Includes only local API tests not requiring access to the Paging Service
 * 
 */

beforeEach(function () {
	baseException = new VPAGER.Exception("","Any VPAGER Exception");
	validationEx = new VPAGER.Exception().ValidationError("");
	illegalParamsEx = new VPAGER.Exception().IllegalParameters("");
	srvRequestEx = new VPAGER.Exception().ServiceRequestError(
			"Service Request Error", "", "");
	
	// Customer Match for VPAGER.Exception objects
	this.addMatchers({
		toThrowVPagerEx:	function(expected) {
			  var result = false;
			  var exception = undefined;
			  if (typeof this.actual != 'function') {
			    throw new Error('Actual is not a function');
			  }
			  try {
			    this.actual();
			  } catch (e) {
			    exception = e;
			  }
			  if (exception) {
			    result = (exception instanceof VPAGER.Exception &&
			    		  expected instanceof VPAGER.Exception &&
			    		  (expected.name === "" || exception.name === expected.name));
			  }
			
			  var not = this.isNot ? "not " : "";
			
			  this.message = function() {
			    if (exception) {
			      return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
			    } else {
			      return "Expected function to throw an exception.";
			    }
			  };
			
			  return result;
		}
	});
});

describe("Logging", function() {
	describe("Logging Tests", function() {
		it("Should handle bad logger", function() {
			var logger = 
				{ 
					message: '',
					no_log_method: function(msg){
							this.message = msg;
						}
				};
			
			new VPAGER.Logging().setLogger(logger);
			expect(VPAGER.Logging().getLogger()).not.toEqual(logger);
			expect(VPAGER.Logging().isEnabled()).toEqual(false);
		});
	
		it("Should take good logger", function() {
			var logger = 
				{ 
					message: '',
					log: function(msg){
							this.message = msg;
						}
				};
			
			new VPAGER.Logging().setLogger(logger);
			expect(VPAGER.Logging().getLogger()).toEqual(logger);
			expect(logger.message).not.toEqual('');
			expect(VPAGER.Logging().isEnabled()).toEqual(true);
		});
	});

	describe("Log4Javascript Setup", function() {
		it("Should install log4javascript", function() {
			if (!VPAGER.Logging().getLogger() ||
			    VPAGER.Logging().getLogger().ID !== "L4JS")
			{
                 // Create an anonymous logger object to redirect log message to TRACE.
                var logger = VPC.createProductionLogger();
                
        		// Install Log4Javascript so trace logging is now in place for 
    			// remainder of unit tests.
    			new VPAGER.Logging().setLogger(logger);
    			expect(VPAGER.Logging().getLogger()).toEqual(logger);
            }
		});
	});
});

describe("WebResult", function() {
	it("Should handle params", function() {
		var wr = new VPAGER.WebResult({
			name : 'test'
		}, 200, null);
		expect(wr.success()).toEqual(true);
		expect(wr.getData().name).toEqual('test');
		expect(wr.getStatus()).toEqual(200);
		expect(wr.getError()).toEqual(null);
	});

	it("Should handle expected errors", function() {
		var wr = new VPAGER.WebResult({
			name : 'test'
		}, 300, 'sample error');
		expect(wr.success()).toEqual(false);
		expect(wr.getData().name).toEqual('test');
		expect(wr.getStatus()).toEqual(300);
		expect(wr.getError()).toEqual('sample error');
	});

	it("Should handle unexpected errors", function() {
		var wr = new VPAGER.WebResult(null, -1, null);
		expect(wr.success()).toEqual(false);
		expect(wr.getData()).toEqual(null);
		expect(wr.getStatus()).toEqual(-1);
		expect(wr.getError()).toEqual(null);
	});

	it("Should handle mismatched params", function() {
		// Setting a success code of 200 but also adding an error message
		var wr = new VPAGER.WebResult(null, 200, 'should not have error msg');
		expect(wr.success()).toEqual(false);
	});
});

describe("ServiceInfo Object", function() {
	var data = null;
	var info = null;
	var status = null;
	
	beforeEach(function () {
		data = {
				ServiceAPIVersion: "0.0.1", 
				Status: {
					NetworkStatus: "NORMAL",
					OverallStatus: "NORMAL"
				},
				UpTime: 4 
		    };
		info = new VPAGER.ServiceInfo(data);
		status = info.getStatus();
	});
	 
	it("Should generate nested objects", function() {
		expect(info.getUpTime()).toEqual(4);
		expect(status instanceof VPAGER.ServiceStatus).toBeTruthy();
		expect(status.getOverallStatus()).toEqual('NORMAL');
	});
	
	it("Should generate property objects", function() {
		var infoProps = info.toProperties();
		expect(infoProps.UpTime).toEqual(4);
		expect(infoProps.Status.OverallStatus).toEqual('NORMAL');
	});
});

describe("PageItem Object Model", function() {

	beforeEach(function () {
		validationEx = new VPAGER.Exception().ValidationError("");
	});
	
	it("Should allow minimum ParentPage creation", function() {
		var pp = new VPAGER.ParentPage({ Code: "123" });
		expect(pp.getType()).toEqual("Parent");
	});
	
	it("Should deserialize ParentPage", function() {
		var data_good1 = {
				ID:		123456,
				Code:	'ABC'
		};
		var data_bad1 = {
				ID:		'',
				Code:	'ABC'
		};
		expect(function(){
			VPAGER.DataElement.deserialize(VPAGER.ParentPage, data_good1);
		   }).not.toThrowVPagerEx(validationEx);
	
		expect(function(){
			VPAGER.DataElement.deserialize(VPAGER.ParentPage, data_bad1);
		   }).toThrowVPagerEx(validationEx);
	
	});

    it("Should detect like Pages", function() {
        var pp1 = new VPAGER.ParentPage({ ID: 1, Code: "123" });
        var pp2 = new VPAGER.ParentPage({ ID: 1, Code: "123" });
        var pp3 = new VPAGER.ParentPage({ ID: 2, Code: "123", Location: "Here" });
        var pp4 = new VPAGER.ParentPage({ ID: 2, Code: "123", Location: "Here" });
        var pp5 = new VPAGER.ParentPage({ ID: 2, Code: "123", Location: "There" });
        // sameAs tests only the ID
        // exactSameAs also tests Code, Location and IsUrgent
        expect(pp1.sameAs(pp2)).toBeTruthy();
        expect(pp2.sameAs(pp3)).toBeFalsy();
        expect(pp3.sameAs(pp4)).toBeTruthy();
        expect(pp3.exactSameAs(pp4)).toBeTruthy();
        expect(pp4.sameAs(pp5)).toBeTruthy();
        expect(pp4.exactSameAs(pp5)).toBeFalsy();
        
    });
    

	
});

describe("ServerProxy API Tests", function() {
	var sp1 = null;
	var sp2 = null;
	var pcode1 = 'T01';
	var pcode2 = 'T02';
	var page1 = null;
	var pageCount = null;
	var request1 = null;
	var request2 = null;

	beforeEach(function() {
		sp1 = new VPAGER.ServerProxy();
		request1 = new VPAGER.ParentPage({ Code: pcode1 });
		request2 = new VPAGER.ParentPage({ Code: pcode2 });
	});

	it("Should initialize", function() {
		sp1.initialize( { serviceURI: SERVICE_URI } );
		expect(sp1.getServiceURI()).toEqual(SERVICE_URI);
	});

	it("Should be a Singleton", function() {
		sp2 = new VPAGER.ServerProxy();
		expect(sp1).toEqual(sp2);
		expect(sp2.getServiceURI()).toEqual(SERVICE_URI);
		expect(new VPAGER.ServerProxy().getServiceURI()).toEqual(SERVICE_URI);
	});

});

describe("EventPublisher", function() {
    var listener1;
    var listener2;
    var etype1 = "TEST_EVENT1";
    var etype2 = "TEST_EVENT2";
    
    beforeEach(function() {
        // Simple Listener definition
        Listener = function() {
            this._called = 0;
            this._type = undefined;
            this._event = undefined;
            this.onVPagerEvent = function(type, event) {
                this._called++;
                this._type = type;
                this._event = event;   
            };
        };
        // Create to Listeners for testing
        listener1 = new Listener();
        listener2 = new Listener();
    });

    it("Accepts Appropriate Listeners", function() {
        publisher = new VPAGER.EventPublisher();
        publisher.registerListener(etype1, listener1);
        expect(publisher.hasListener(etype1, listener1)).toBeTruthy();
    });
    
    it("Rejects Inappropriate Listeners", function() {
        publisher = new VPAGER.EventPublisher();
        publisher.registerListener(etype1, {});
        expect(publisher.hasListener(etype1, listener1)).toBeFalsy();
    });
    
    it("Can support Multiple Listeners", function() {
        publisher = new VPAGER.EventPublisher();
        publisher.registerListener(etype1, listener1);
        publisher.registerListener(etype1, listener2);
        publisher.registerListener(etype2, listener2);
        expect(publisher.hasListener(etype1, listener1)).toBeTruthy();
        expect(publisher.hasListener(etype1, listener2)).toBeTruthy();
        expect(publisher.hasListener(etype2, listener1)).toBeFalsy();
        expect(publisher.hasListener(etype2, listener2)).toBeTruthy();
        expect(publisher.getListenerCount(etype1)).toEqual(2);
        expect(publisher.getListenerCount(etype2)).toEqual(1);
    });
    
    it("Can support deregistration", function() {
        publisher = new VPAGER.EventPublisher();
        // Register the listeners
        publisher.registerListener(etype1, listener1);
        publisher.registerListener(etype1, listener2);
        publisher.registerListener(etype2, listener2);
        // Verify registration
        expect(publisher.hasListener(etype1, listener1)).toBeTruthy();
        expect(publisher.hasListener(etype1, listener2)).toBeTruthy();
        expect(publisher.hasListener(etype2, listener2)).toBeTruthy();
        
        // Deregister 2 of the 3
        publisher.deregisterListener(etype1, listener1);
        publisher.deregisterListener(etype2, listener2);
        // Verify partial deregistration
        expect(publisher.hasListener(etype1, listener1)).toBeFalsy();
        expect(publisher.hasListener(etype1, listener2)).toBeTruthy();
        expect(publisher.hasListener(etype2, listener2)).toBeFalsy();
    });

    it("Can publish events", function() {
        // Register the listeners
        publisher = new VPAGER.EventPublisher();
        publisher.registerListener(etype1, listener1);
        publisher.registerListener(etype1, listener2);
        publisher.registerListener(etype2, listener2);
        
        // Publish events
        publisher.publishEvent(etype1, {name: "TestEventA"});
        publisher.publishEvent(etype2, {name: "TestEventB"});
        
        // Verify Listeners received them
        expect(listener1._called).toEqual(1);
        expect(listener1._type).toEqual(etype1);
        expect(listener1._event.name).toEqual("TestEventA");
        expect(listener2._called).toEqual(2);
        expect(listener2._type).toEqual(etype2);
        expect(listener2._event.name).toEqual("TestEventB");
    });
        
    
});


